package uscdb.service;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.regex.Pattern;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import uscdb.dao.LogicDaoI;
import uscdb.model.Tlogic;
import uscdb.pageModel.Logic;
import uscdb.util.StringUtil.ClobUtil;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:spring.xml", "classpath:spring-hibernate.xml" })
public class SplitLogic {

	@Autowired
	private LogicServiceI logicService;

	@Autowired
	private LogicDaoI LogicDao;

	@Autowired
	private SessionFactory sessionFactory;

	@Test
	// 这个方式是从头往尾读取数据
	public void readLogic() {
		try {
			// 逻辑名的模式
			String logicNameReg = "^(Logic|Join)\\s+(\\w+)\\s\\{.*";
			Pattern logicNamePattern = Pattern.compile(logicNameReg);

			// 逻辑结尾的模式
			String endLogicReg = "\\s+}.*|}.*";
			Pattern endLogicPattern = Pattern.compile(endLogicReg);

			// 读取文件
			BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("test.logic"), "gbk"));
			String data = null;
			String logicName = "";
			String logicBody = "";
			// 暂时存放结束符与下一个logic头中间部分
			String logicBodyTemp = "";

			Boolean endLogicFlag = false;
			while ((data = br.readLine()) != null) {
				// System.out.println(data);
				// 并且对每一行扫描，匹配出逻辑名
				java.util.regex.Matcher logicNameMatcher = logicNamePattern.matcher(data);

				if (logicNameMatcher.matches()) {
					if (endLogicFlag) {
						// System.out.println(logicBodyTemp);
						// System.out.println(logicBody);
						logicBody = logicBody.substring(logicBodyTemp.length());

						// 初始化logic对象
						Logic logic = new Logic();
						logic.setId(UUID.randomUUID().toString());
						logic.setTitle(logicName);
						logicBodyTemp = logicBodyTemp.replaceAll(" ", " &nbsp;");
						logic.setContent(logicBodyTemp.substring(0, logicBodyTemp.length() - 4));

						// 保存logic对象
						 Session session = sessionFactory.openSession();
						 session.getTransaction().begin();
						 logicService.add(logic);
						 session.getTransaction().commit();
						System.out.println(logic);

						// 获取下一个逻辑的名字
						logicName = logicNameMatcher.group(2);

					} else {
						logicName = logicNameMatcher.group(2);
						// System.out.println("logicName : " + logicName);
					}
				}

				// 匹配是否一个逻辑的结束标记
				java.util.regex.Matcher endLogicmatcher = endLogicPattern.matcher(data);
				
				// 没遇到结尾之前的每一行，都直接存在变量里
				logicBody += data + "<br>";
				
				// 如果匹配上
				if (endLogicmatcher.matches()) {
					// 暂时存放起来，继续寻找下一个logic头
					logicBodyTemp = logicBody;
					endLogicFlag = true;
					continue;
				}

			}

			// 当达到最后一行，当然也是处理最后一个logic
			// 初始化logic对象
			Logic logic = new Logic();
			logic.setId(UUID.randomUUID().toString());
			logic.setTitle(logicName);
			logicBody = logicBody.replaceAll(" ", " &nbsp;");
			logic.setContent(logicBody);

			Session session = sessionFactory.openSession();
			session.getTransaction().begin();
			logicService.add(logic);
			session.getTransaction().commit();

			System.out.println(logic);

			br.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void writeLogic() {
		try {
			Map<String, Object> params = new HashMap<>();
			params.put("modifydatetime", new Date());

			FileWriter writer = new FileWriter("./download.logic", true);
			Session session = sessionFactory.getCurrentSession();
			session.getTransaction().begin();
			List<Tlogic> tlogicList = LogicDao.find("from Tlogic t where t.modifydatetime < :modifydatetime", params);
			session.getTransaction().commit();
			for (Tlogic tlogic : tlogicList) {
				String content = ClobUtil.getString(tlogic.getContent());
				for (String s : content.split("<br>")) {
					System.out.println(s);
					// 把html的空格转换回文件的空格
					s = s.replaceAll(" &nbsp;", " ");
					writer.write(s + "\n");
					// writer.flush();
				}
			}
			writer.close();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	@Test
	// 这个方法是从尾往头读取数据
	public void testRandomAccessFile() {
		RandomAccessFile rf = null;
		try {
			// 这个是逻辑头
			String logicNameReg = "^(Logic|Join)\\s+(\\w+)\\s\\{.*";
			Pattern logicNamePattern = Pattern.compile(logicNameReg);

			// 这个是逻辑结束，需要注意 以下几种情况，一种是靠边结束，一种是不靠边结束，一种是几个右大括号结束
			String endLogicReg = "\\s+}.*|}.*";
			Pattern endLogicPattern = Pattern.compile(endLogicReg);

			// 文件摘要的关键字，扫描到这个马上break
			String logicFileSummaryReg = "^#!\\+==.*";
			Pattern logicFileSummaryPattern = Pattern.compile(logicFileSummaryReg);

			rf = new RandomAccessFile("test.logic", "r");
			// 文件长度
			long len = rf.length();
			long start = rf.getFilePointer();
			// 指针是从0到length-1
			long nextend = start + len - 1;
			String line;
			String logicName = "";
			String logicBody = "";
			// 当寻找到一个逻辑的名字，才开启寻找上一个逻辑右大括号的功能
			Boolean searchEndLogicFlag = false;
			// seek到最后一个字符
			rf.seek(nextend);
			int c = -1;
			while (nextend > start) {
				c = rf.read();
				// 只有行与行之间才有\r\n，这表示读到每一行上一行的末尾的\n，而执行完read后，
				// 指针指到了这一行的开头字符
				if (c == '\n' || c == '\r') {
					line = rf.readLine();
					if (line == null) {// 处理文件末尾是空行这种情况
						nextend--;
						rf.seek(nextend);
						continue;
					}
					if (line != null) {
						// 把获取的字符串整合成逻辑
						logicBody = new String(line.getBytes("ISO-8859-1"), "gbk") + logicBody;

						// 获取 logic名;
						java.util.regex.Matcher logicNameMatcher = logicNamePattern.matcher(line);
						if (logicNameMatcher.matches()) {
							logicName = logicNameMatcher.group(2);
							System.out.println("logicName : " + logicName);
							searchEndLogicFlag = true;
						}

						// 一旦获取logic名，向上再找到一个右大括号，就算是目前的logic结束
						java.util.regex.Matcher endLogicMatcher = endLogicPattern.matcher(line);
						if (endLogicMatcher.matches() && searchEndLogicFlag) {
							// 封装完一个logic；游标退回该右大括号之前；logicBody清空
							logicBody = logicBody.substring(1, logicBody.length());
							System.out.println("logicBody : " + logicBody);
							nextend += line.length();
							logicBody = "";
							searchEndLogicFlag = false;
							continue;
						}

						// 文件摘要的关键字，扫描到这个马上break
						java.util.regex.Matcher logicFileSummaryMatcher = logicFileSummaryPattern.matcher(line);
						if (logicFileSummaryMatcher.matches()) {
							// 封装完一个logic；logicBody清空
							logicBody = logicBody.substring(line.length(), logicBody.length());
							System.out.println("logicBody : " + logicBody);
							logicBody = "";
							searchEndLogicFlag = false;
							break;
						}

						// System.out.println(new
						// String(line.getBytes("ISO-8859-1"), "gbk"));
					}
					nextend--;
				}
				nextend--;
				rf.seek(nextend);
				if (nextend == 0) {// 当文件指针退至文件开始处，输出第一行
					System.out.println("输出第一行" + rf.readLine());
				}
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (rf != null)
					rf.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

}
